#include "los_base.h"
#include "los_config.h"
#include "los_process_pri.h"
#include "lwip/init.h"
#include "lwip/tcpip.h"
#include "sys/mount.h"
#include "mtd_partition.h"
#include "console.h"

UINT32 OsRandomStackGuard(VOID)
{
    return 0;
}

static void sun8i_board_init()
{
    uint32_t val;
    READ_UINT32(val, IO_DEVICE_ADDR(0x01c202c0));
    val |= BIT(17) | BIT(20);
    WRITE_UINT32(val, IO_DEVICE_ADDR(0x01c202c0));
    READ_UINT32(val, IO_DEVICE_ADDR(0x01c20060));
    val |= BIT(17) | BIT(20);
    WRITE_UINT32(val, IO_DEVICE_ADDR(0x01c20060));

    READ_UINT32(val, IO_DEVICE_ADDR(0x01c202d8));
    val |= BIT(0);
    WRITE_UINT32(val, IO_DEVICE_ADDR(0x01c202d8));

    READ_UINT32(val, IO_DEVICE_ADDR(0x01c2006c)); 
    val |= BIT(0);
    WRITE_UINT32(val, IO_DEVICE_ADDR(0x01c2006c));
    WRITE_UINT32(0x80000000, IO_DEVICE_ADDR(0x01c200a0));

    READ_UINT32(val, IO_DEVICE_ADDR(0x01c20824));
    val &= ~(7 << 24);
    val &= ~(7 << 28);
    val |= (2 <<  24) | (2 << 28);
    WRITE_UINT32(val, IO_DEVICE_ADDR(0x01c20824));
}

static void sun8i_mount_rootfs()
{
    dprintf("register parition ...\n");
    if (add_mtd_partition("spinor", 0x600000, 0x800000, 0))
    {
        PRINT_ERR("add_mtd_partition fail\n");
    }
    
    dprintf("mount /dev/spinorblk0 / ...\n");
    if (mount("/dev/spinorblk0", "/", "jffs2", MS_RDONLY, NULL))
    {
        PRINT_ERR("mount failed\n");
    }
}

static void sun8i_driver_init()
{
    extern int spinor_init(void);
    dprintf("spinor_init init ...\n");
    if (!spinor_init())
    {
        PRINT_ERR("spinor_init failed\n");
    }

    dprintf("tcpip_init ...\n");
    tcpip_init(NULL, NULL);

    dprintf("ethnet_sun8i_eth_init init ...\n");
    extern void ethnet_sun8i_eth_init(void);
    ethnet_sun8i_eth_init();

    dprintf("sunxifb_init init ...\n");
    extern int sunxifb_init(void);
    if (sunxifb_init())
    {
        PRINT_ERR("sunxifb_init failed\n");
    }
}


void SystemInit()
{
	sun8i_board_init();

#ifdef LOSCFG_FS_PROC
    dprintf("proc fs init ...\n");
    extern void ProcFsInit(void);
    ProcFsInit();
#endif

#ifdef LOSCFG_DRIVERS_MEM
    dprintf("mem dev init ...\n");
    extern int mem_dev_register(void);
    mem_dev_register();
#endif
    sun8i_driver_init();
    sun8i_mount_rootfs();

    extern int uart_dev_init(void);
    uart_dev_init();

    if (virtual_serial_init("/dev/uartdev-0") != 0)
    {
        PRINT_ERR("virtual_serial_init failed");
    }

    if (system_console_init(SERIAL) != 0)
    {
        PRINT_ERR("system_console_init failed\n");
    }

    if (OsUserInitProcess())
    {
        PRINT_ERR("Create user init process faialed!\n");
    }
}

